package com.onpositive.datacollection.proxy;

import java.util.ArrayList;
import java.util.HashMap;

import com.onpositive.data.IPropertyMetadata;
import com.onpositive.data.kvstorage.KeyValueBasedCollection;
import com.onpositive.datamap.IDataPropertyValue;
import com.onpositive.datamap.core.IDataObject;
import com.onpositive.datamap.core.IDataProperty;
import com.onpositive.datamap.core.IImageObject;
import com.onpositive.datamap.core.IPropertyGroup;
import com.onpositive.datamap.core.ITextSection;
import com.onpositive.datamap.core.impl.AbstractDataProperty;
import com.onpositive.datamap.core.impl.DataCollection;
import com.onpositive.datamap.core.impl.DataObject;
import com.onpositive.datamap.core.impl.SimpleProperty;
import com.onpositive.datamap.item.SingleDataObject;
import com.onpositive.datamap.values.impl.ValueSequence;
import com.onpositive.semantic.model.api.meta.BaseMeta;
import com.onpositive.semantic.model.api.meta.IHasMeta;
import com.onpositive.semantic.model.api.meta.MetaAccess;
import com.onpositive.semantic.model.api.property.IProperty;
import com.onpositive.semantic.model.api.property.ValueUtils;
import com.onpositive.semantic.model.api.realm.IRealm;
import com.onpositive.semantic.model.api.realm.IRealmProvider;
import com.onpositive.semantic.model.api.realm.Realm;

public class RemoteDataCollection extends DataCollection {

	public final class RemoteDataObject extends DataObject {
		public RemoteDataObject(DataCollection dataCollection, int num) {
			super(dataCollection, num);
		}

		@Override
		public ITextSection getTextDescription() {
			SingleDataObject m = accuire(this.getUID());
			return m.getTextDescription();
		}

		public String getTextContentAsString() {
			SingleDataObject m = accuire(this.getUID());
			return m.getTextContentAsString();
		}

		@Override
		public IImageObject getPreviewImage() {
			SingleDataObject m = accuire(this.getUID());
			return m.getPreviewImage();
		}

		@Override
		public IImageObject getPrimaryImage() {
			SingleDataObject m = accuire(this.getUID());
			return m.getPrimaryImage();
		}

		public IDataObject toSingle() {
			return accuire(getCaption());
		}
	}

	protected IRemoteCollectionProxy proxy;

	private String id;

	public RemoteDataCollection(String id, IRemoteCollectionProxy proxy) {
		super(new RemoteObjectCollection(proxy, id, proxy.getDetailedInfo(id)),
				null, null);
		((RemoteObjectCollection) getCollection()).c = this;
		this.id = id;
		this.proxy = proxy;
	}
	@Override
	protected IDataProperty createProperty(IPropertyMetadata m) {
		final IDataProperty createProperty = super.createProperty(m);
		BaseMeta mp=(BaseMeta) MetaAccess.getMeta(createProperty).getMeta();
		mp.registerService(IRealmProvider.class, new IRealmProvider<Object>() {

			/**
			 * 
			 */
			private static final long serialVersionUID = 1L;

			@SuppressWarnings({ "unchecked", "rawtypes" })
			@Override
			public IRealm<Object> getRealm(IHasMeta model,
					Object parentObject, Object object) {
				IRealm<?> realm = RemoteDataCollection.this.getRealm();
				ArrayList<Object>m=new ArrayList<Object>();
				for (Object q:realm.getContents()){
					Object value = createProperty.getValue(q);
					if (value instanceof ValueSequence){
						ValueSequence v=(ValueSequence) value;
						value=v.getParts();
					}
					m.addAll(ValueUtils.toCollection(value));
				}
				return new Realm(m);
			}
		});
		return createProperty;
	}

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	protected HashMap<String, SingleDataObject> map = new HashMap<String, SingleDataObject>();

	@Override
	protected DataObject createDataObject(int num) {
		return new RemoteDataObject(this, num);
	}
	
	@Override
	protected void onPropertyGroupsChanged() {
		super.onPropertyGroupsChanged();
		proxy.updatePropertyGroups(id,pgroups.getContents().toArray(new IPropertyGroup[pgroups.size()]));
	}

	protected SingleDataObject accuire(String uid) {
		SingleDataObject singleDataObject = map.get(uid);
		if (singleDataObject != null) {
			return singleDataObject;
		}
		SingleDataObject object = proxy.getObject(id, uid);
		SingleDataObject q = new SingleDataObject(object) {

			boolean inited;
			/**
			 * 
			 */
			{
				inited = true;
			}
			private static final long serialVersionUID = 1L;

			@Override
			public Iterable<IProperty> getProperties(Object obj) {
				return RemoteDataCollection.this.getProperties(null);
			}

			@Override
			protected void postSet(IDataObject obj, AbstractDataProperty p,
					Object value) {
				if (inited) {
					if (value instanceof String && p instanceof SimpleProperty) {
						value = new ValueSequence(p, null,
								new String[] { (String) value });
					}
					if (value instanceof String[]
							&& p instanceof SimpleProperty) {
						value = new ValueSequence(p, null, (String[]) value);
					}
					if (value instanceof IDataPropertyValue) {
						IDataPropertyValue q = (IDataPropertyValue) value;
						value = q.clone(null);
					}
					proxy.putValue(id, obj.getCaption(), p.getId(), value);
					super.postSet(obj, p, value);
				}
			}

		};
		map.put(uid, q);
		return q;
	}

	@Override
	protected void updateMeta(String id) {
		IPropertyMetadata property = getCollection().getProperty(id);
		proxy.updateMeta(this.id, property);		
	}
}
